home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-08-13 | 22.2 KB | 899 lines | [TEXT/KEEN] |
- #$ClipFormatFuncIntro: pretty up the start of a function, down to last local
- #variable at beginning of function definition.
- # Use the "Set Variables" button in the hAWK dialog to set the value
- # of spaces_in_tab if it is different from 4.
- # The preset variable "convert_comments", if left to its default value of 1,
- # will signal conversion of /*...*/ comments to one or more // comments.
- # Set it to 0 if you don't want this.
- # Usage: start this program (first adjust the preset vars described above
- # if necessary); to reformat a function start, type "ff" just at the start
- # of the function, select full lines from there down to the end of the
- # local variable declarations at the top of the function, Copy, wait
- # for the menu bar to flash, and Paste. If nothing changes, hit <Command><period>
- #to stop the program in the usual way, and the stderr window will appear with
- # a (rough) diagnostic message of what went wrong. Most common problem, including
- # something that isn't a local variable declaration in the local section, such
- # as a define or a prototype. (If you want some fun, teach this program to handle them)
-
- # This program, like other "magic clipboard" programs, should eventuall be halted
- # by typing <Command><period>. Note it does nothing at all unless you Copy something
- # that begins with "ff".
-
- # Just for example, below you would type in the "ff" just before "Boolean"
- # to signal this program that you want a function formatted; then select
- # all complete lines from the "ff" down to "shiftDown);", then Copy,...
-
- #ffBoolean AddSimilarFiles(Boolean isSysHeader, long *fileKeyPtr) /* start of messy function */
- # {
- # WindowDataPtr wdPtr = GetProjectPtr(); // hey it's a standard window data pointer
- # char fileName[32]; /*comment broken across
- # two lines */
- # long startDirID;/* directory to start search from */
- # short j, index, vRefNum, whichPane;
- # short q=2;//completely arbitrary comment here
- # Boolean filesAdded = FALSE;
- # Boolean searchSubs = (gEvtDetails.optionDown || gEvtDetails.shiftDown);
-
- # ...wait for the menu bar to flash, and then Paste to get
-
- #Boolean AddSimilarFiles
- # (Boolean isSysHeader, //
- # long *fileKeyPtr) // start of messy function
- # {
- # WindowDataPtr wdPtr = GetProjectPtr();// hey it's a standard window data pointer
- # char fileName[ 32 ]; // comment broken across
- # // two lines
- # long startDirID; // directory to start search from
- # short j; //
- # short index; //
- # short vRefNum; //
- # short whichPane; //
- # short q =2; // completely arbitrary comment here
- # Boolean filesAdded = FALSE; //
- # Boolean searchSubs = (gEvtDetails.optionDown || gEvtDetails.shiftDown);//
-
- # This still has some minor problems -- eg the "start of messy function" comment will probably
- # have to be moved up to just above the start of the function - but it was a pretty lame
- # comment anyway, and shouldn't really have been there. The multi-line comment that covers
- # two lines has been converted to two single-line comments, but the tabbing will have to
- # be adjusted. The huge last line might look better if split across two lines.
-
-
- # This program runs until terminated with <Command><period>
- # It reformats copied function starts nicely, provided the clip begins with "ff"
- BEGIN {
- clipCharsToWatch = 32;
- init();
- # Check user-set variables
- if (spaces_in_tab+0 < 1)
- spaces_in_tab = 4;
- if (convert_comments+0 != 0)
- convert_comments = 1;
- while (1) # run until <Command><period>...
- {
- # see if clipboard has changed
- if ((newClip = getclip(clipCharsToWatch)) != oldClip)
- {
- oldClip = newClip;
- # "ff" at start is used as the trigger
- if (index(newClip, "ff") == 1)
- ReformatFuncIntro();
- }
- }
- }
-
- function ReformatFuncIntro()
- {
- # clear toktype, error flag, output
- toktype = 0;
- error = 0;
- out = ""
- var_number = 0;
- last_param = 0;
- last_local = 0;
- # also clean out arrays
- clean_arrays();
- temp = getclip(); # gets calling editor's private clip
- # strip leading ff
- clip = substr(temp, 3);
- temp = "";
- # parse the clip as a function beginning
- func_beginning();
- # output the reformatted function beginning to "out"
- if (error == 0)
- output_reformatted_beginning();
- # send the result back to the calling editor's clip
- if (error == 0)
- putclip(out);
- # update "oldClip"
- if (error == 0)
- oldClip = substr(out, 1, 32);
- # flash menu bar to signal something happened
- if (error == 0)
- beep(0);
- else
- {
- beep(0);
- beep(0);
- beep(0);
- }
- }
-
- # clean out var_type[i] var_name[i] var_init[i] var_comment[i]
- function clean_arrays()
- {
- for (i in var_type)
- delete var_type[i];
- for (i in var_name)
- delete var_name[i];
- for (i in var_init)
- delete var_init[i];
- for (i in var_comment)
- delete var_comment[i];
- }
-
- # parse the clip as a function beginning
- # func_beginning : stuff_before_paren '(' param_decls ')' '{' local_decls
- function func_beginning()
- {
- # collect stuff_before_paren
- stuff_before_paren();
- # require hit '(' here
- advance();
- require(tok == "(", "No opening paren");
- if (error) return;
- advance();
- # collect param declarations
- param_decls();
- # require ')'
- require(tok == ")", "No closing paren");
- if (error) return;
- advance();
- # pick up any comment after ')'
- if (toktype == COMMENT)
- {
- var_comment[var_number] = tok;
- advance();
- }
- if (error) return;
- # record divider between params and locals
- last_param = var_number;
- # if '{' follows, do the locals too
- if (tok == "{")
- {
- advance();
- # collect local declarations
- local_decls();
- last_local = var_number;
- }
- else if (toktype != EOF)
- require(0, "expected { or nothing after parameters");
- }
-
- # match up to just before '(', wherever it is
- function stuff_before_paren()
- {
- if (match(clip, /\(/))
- {
- opening = substr(clip, 1, RSTART-1)
- clip = substr(clip, RSTART)
- }
- }
-
- # param_decls : param_decl {{comment}','{comment} paramdecl}
- function param_decls()
- {
-
- while (tok != ")" && toktype != EOF)
- {
- param_decl();
- if (toktype == COMMENT)
- {
- # record the comment
- var_comment[var_number] = tok;
- advance();
- if (tok == ",")
- {
- advance();
- if (toktype == COMMENT)
- {
- # record the comment
- var_comment[var_number] = tok;
- advance();
- }
- }
- }
- else if (tok != "," && tok != ")" && toktype != EOF)
- {
- require(0, "illegal looking params");
- }
- if (tok == ",")
- {
- advance();
- if (toktype == COMMENT)
- {
- # record the comment
- var_comment[var_number] = tok;
- advance();
- }
- }
- }
- require(toktype != EOF, "unexpected EOF in function parameters");
- }
-
- # param_decl : type_name [star_name]
- # type_name : name | '...'
- function param_decl()
- {
- if (toktype == NAME)
- {
- # collect various keywords that might come before a type name proper
- if (tok == "static" || tok == "const" || tok == "volatile"\
- || tok == "extern" || tok == "register"\
- || tok == "signed" || tok == "unsigned")
- {
- var_type[++var_number] = tok;
- advance();
- while (tok == "static" || tok == "const" || tok == "volatile"\
- || tok == "extern" || tok == "register"\
- || tok == "signed" || tok == "unsigned")
- {
- var_type[var_number] = var_type[var_number] " " tok;
- advance();
- }
- #the type name proper
- if (toktype == NAME)
- {
- var_type[var_number] = var_type[var_number] " " tok;
- advance();
- }
- else
- require(0, "stat unexpected token while looking for param type");
- }
- else
- {
- var_type[++var_number] = tok;
- advance();
- }
- # the parameter name (with adornments), optional
- if (toktype == "*" || toktype == NAME)
- star_name();
- }
- else
- require(0, "unexpected token while looking for param type");
- }
-
- # star_name : {'*'}name{'['.*']'}
- function star_name()
- {
- if (tok == "*")
- {
- while (tok == "*")
- {
- var_name[var_number] = var_name[var_number] tok;
- advance();
- }
- }
- if (toktype == NAME)
- {
- var_name[var_number] = var_name[var_number] tok;
- advance();
- }
- else
- require(0, "unexpected token while looking for name");
- while (tok == "[")
- {
- var_name[var_number] = var_name[var_number] tok;
- advance();
- while (tok != "]" && toktype != EOF)
- {
- if (tok == ",")
- var_name[var_number] = var_name[var_number] tok;
- else
- var_name[var_number] = var_name[var_number] " " tok;
- advance();
- }
- if (toktype != EOF)
- {
- var_name[var_number] = var_name[var_number] " " tok;
- advance();
- }
- else
- require(0, "unexpected end of clip while looking for ]");
- }
- }
-
- # collect local declarations
- # local_decls : local_decl* to end of clip
- function local_decls()
- {
- while (toktype != EOF)
- local_decl();
- }
-
- # local_decl : type_name local_name {',' {comment} local_name} ';' {comment}
- # note here var_number is incremented when local_name seen, not when type_name seen.
- function local_decl()
- {
-
- if (toktype == NAME)
- {
- if (tok == "static" || tok == "const" || tok == "volatile"\
- || tok == "extern" || tok == "register"\
- || tok == "signed" || tok == "unsigned")
- {
- cur_var_type = tok;
- advance();
- while (tok == "static" || tok == "const" || tok == "volatile"\
- || tok == "extern" || tok == "register"\
- || tok == "signed" || tok == "unsigned")
- {
- cur_var_type = cur_var_type " " tok;
- advance();
- }
- if (toktype == NAME)
- {
- cur_var_type = cur_var_type " " tok;
- advance();
- }
- else
- require(0, "stat unexpected token while looking for local var type");
- }
- else
- {
- cur_var_type = tok;
- advance();
- }
- if (toktype == "*" || toktype == NAME)
- {
- local_name();
- # continue for all decls with same type, and pick up comments
- while (tok != ";" && toktype != EOF)
- {
- if (tok == ",")
- advance();
- if (toktype == COMMENT)
- {
- # record the comment
- var_comment[var_number] = tok;
- advance();
- }
- if (toktype == "*" || toktype == NAME)
- {
- local_name();
- }
- # may lock up on eg a function declaration
- if (tok != ";" && tok != ",")
- require(0, "unexpected token while looking for local name or semicolon or EOF");
- }
- if (tok == ";")
- advance();
- if (toktype == COMMENT)
- {
- # record the comment
- var_comment[var_number] = tok;
- advance();
- }
- }
- else
- require(0, "unexpected token while looking for local name");
- }
- else
- require(0, "unexpected token while looking for local var type");
- }
-
- # local_name : star_name {'=' var_init}
- function local_name()
- {
- var_type[++var_number] = cur_var_type;
- star_name();
- if (tok == "=")
- {
- var_init[var_number] = " " tok;
- #advance(); - get init now being done behind lexer's back via "match"
- get_initter();
- }
- }
-
- # var_init : stuff in '{}' or all up to ',' or ';' or EOF
- # -left unparsed, to avoid having to put whitespace back in
- function get_initter()
- {
- if (tok == "{")
- {
- if (match(clip, /^[^}]+}/))
- {
- var_init[var_number] = var_init[var_number] substr(clip, 1, RLENGTH);
- clip = substr(clip, RLENGTH+1)
- advance();
- }
- else
- require(0, "unbalanced curly initializer");
- }
- else
- {
- if (match(clip, /^[^,;]+[,;]/))
- {
- var_init[var_number] = var_init[var_number] substr(clip, 1, RLENGTH-1);
- clip = substr(clip, RLENGTH)
- advance();
- }
- else
- require(0, "unbalanced initializer");
- }
- # Old version, putting whitespace back in proved too tedious....
- # previous_toktype = toktype;
- #
- # if (tok == "{")
- # {
- # while (tok != "}" && tok != ";" && toktype != EOF)
- # {
- # if (tok == "," || (tok == "(" && previous_toktype == NAME))
- # var_init[var_number] = var_init[var_number] tok;
- # else
- # var_init[var_number] = var_init[var_number] " " tok;
- # previous_toktype = toktype;
- # advance();
- # }
- # if (tok == "}")
- # {
- # var_init[var_number] = var_init[var_number] " " tok;
- # advance();
- # }
- # }
- # while (tok != "," && tok != ";" && toktype != EOF)
- # {
- # if (tok == "(" && previous_toktype == NAME)
- # var_init[var_number] = var_init[var_number] tok;
- # else
- # var_init[var_number] = var_init[var_number] " " tok;
- # previous_toktype = toktype;
- # advance();
- # }
- }
-
-
-
- ## output functions **
- # Do the output to "out", which will become the new clip.
- function output_reformatted_beginning()
- {
- OutputDecl();
- OutputLocals();
- }
-
- # Output func intro and nicely formatted params, and '{'.
- function OutputDecl( longest_type, longest_name, first_inc)
- {
- # special handling for case of single param
- if (last_param == 1)
- {
- if (var_name[1] != "")
- var_type[1] = var_type[1] " ";
- if (var_comment[1] != "")
- var_comment[1] = "\t" var_comment[1];
- else
- var_comment[1] = "\t// "
- out = opening "(" var_type[1] var_name[1] ")" var_comment[1] "\r\t{\r";
- }
- else if (last_param > 0)
- {
- out = opening "\r";
- #calculate longest type and param name, and stick the commas in
- longest_type = 0;
- longest_name = 0;
- for (i = 1; i <= last_param; ++i)
- {
- if (i == 1)
- var_type[i] = "(" var_type[i];
- if (longest_type < length(var_type[i]))
- longest_type = length(var_type[i])
- if (i < last_param)
- var_name[i] = var_name[i] ","
- else
- var_name[i] = var_name[i] ")"
- if (longest_name < length(var_name[i]))
- longest_name = length(var_name[i])
- }
- # adjust up to next tab boundary
- if (longest_type % spaces_in_tab)
- longest_type += spaces_in_tab - longest_type % spaces_in_tab;
- if (longest_name % spaces_in_tab)
- longest_name += spaces_in_tab - longest_name % spaces_in_tab;
- # and add a tab
- longest_type += spaces_in_tab;
- longest_name += spaces_in_tab;
- # now spit them out
- for (i = 1; i <= last_param; ++i)
- {
- # adjust type names
- diff = longest_type - length(var_type[i])
- first_inc = spaces_in_tab - length(var_type[i]) % spaces_in_tab;
- var_type[i] = "\t" var_type[i];
- if (first_inc == spaces_in_tab)
- first_inc = 0;
- if (first_inc)
- {
- var_type[i] = var_type[i] "\t";
- diff -= first_inc;
- }
- while (diff > 0)
- {
- var_type[i] = var_type[i] "\t";
- diff -= spaces_in_tab;
- }
- # adjust param names (if present)
- if (var_name[i] != "")
- {
- diff = longest_name - length(var_name[i])
- first_inc = spaces_in_tab - length(var_name[i]) % spaces_in_tab;
- if (first_inc == spaces_in_tab)
- first_inc = 0;
- if (first_inc)
- {
- var_name[i] = var_name[i] "\t";
- diff -= first_inc;
- }
- while (diff > 0)
- {
- var_name[i] = var_name[i] "\t";
- diff -= spaces_in_tab;
- }
- }
- # create dummy comment if none present
- if (var_comment[i] == "")
- var_comment[i] = "// ";
- # out go type, name, comment
- out = out var_type[i] var_name[i] var_comment[i] "\r";
- }
- out = out "\t{\r";
- }
- }
-
- # Output nicely formatted local definitions - note locals are optional
- function OutputLocals( longest_type, longest_name, first_inc)
- {
- if (last_local <= last_param)
- return;
- #calculate longest type and param name
- longest_type = 0;
- longest_name = 0;
- for (i = last_param+1; i <= last_local; ++i)
- {
- if (longest_type < length(var_type[i]))
- longest_type = length(var_type[i])
- if (longest_name < length(var_name[i]))
- longest_name = length(var_name[i])
- }
- longest_name += 1; # 1 extra for ';'
- # adjust up to next tab boundary
- if (longest_type % spaces_in_tab)
- longest_type += spaces_in_tab - longest_type % spaces_in_tab;
- if (longest_name % spaces_in_tab)
- longest_name += spaces_in_tab - longest_name % spaces_in_tab;
- # and add a tab
- longest_type += spaces_in_tab;
- longest_name += spaces_in_tab;
- # sneaky trick, attempt to squeeze short inits in with var_name
- for (i = last_param+1; i <= last_local; ++i)
- {
- if (length(var_type[i]) + length(var_init[i]) + 1 <= longest_name)
- {
- var_name[i] = var_name[i] var_init[i];
- delete var_init[i];
- }
- }
- # now spit them out
- for (i = last_param+1; i <= last_local; ++i)
- {
- # adjust type names
- diff = longest_type - length(var_type[i])
- first_inc = spaces_in_tab - length(var_type[i]) % spaces_in_tab;
- var_type[i] = "\t" var_type[i];
- if (first_inc == spaces_in_tab)
- first_inc = 0;
- if (first_inc)
- {
- var_type[i] = var_type[i] "\t";
- diff -= first_inc;
- }
- while (diff > 0)
- {
- var_type[i] = var_type[i] "\t";
- diff -= spaces_in_tab;
- }
- # adjust local names (always present), and append a semicolon, if no init
- if (!(i in var_init) || var_init[i] == "")
- {
- var_name[i] = var_name[i] ";";
- diff = longest_name - length(var_name[i])
- first_inc = spaces_in_tab - length(var_name[i]) % spaces_in_tab;
- if (first_inc == spaces_in_tab)
- first_inc = 0;
- if (first_inc)
- {
- var_name[i] = var_name[i] "\t";
- diff -= first_inc;
- }
- while (diff > 0)
- {
- var_name[i] = var_name[i] "\t";
- diff -= spaces_in_tab;
- }
- }
- else
- var_name[i] = var_name[i] var_init[i] ";";
- # create dummy comment if none present
- if (var_comment[i] == "")
- var_comment[i] = "// ";
- # out go type, name, var_init, comment
- #temp = var_type[i] var_name[i] var_init[i] var_comment[i];
- # var_init has been thrown in with var_name just above
- temp = var_type[i] var_name[i] var_comment[i];
- out = out temp "\r";
- }
- }
-
-
- ## lexical functions ##
- function init()
- {
- NAME = 256
- STRING = 257
- CHAR_CONSTANT = 258
- NUMBER = 259
- KEY = 260
- BITASSIGNOP = 261
- ASSIGNOP = 262
- LEX_OR = 263
- LEX_AND = 264
- RELOP = 265
- SHIFT = 266
- INCREMENT = 267
- DECREMENT = 268
- POINTER = 269
- OTHER = 270
- COMMENT = 271
- EOF = 272
- MEMBEROP = 273
- ILLEGAL = 274
-
- }
-
- # A simple, incomplete lexical analyzer for C - note it returns comments as tokens
- function advance()
- {
- if (clip == "" || error != 0)
- {
- toktype = EOF;
- return;
- }
- if (toktype == EOF) return
- if (tok == "." || tok == "->") #member coming, not a local
- {
- if (match(clip, /^[A-Za-z_](\w|_)*/))
- {
- tok = substr(clip, 1, RLENGTH)
- clip = substr(clip, RLENGTH+1)
- toktype = OTHER
- return
- }
- else
- require(0, "missing member name")
- }
- toktype = ILLEGAL
- # grab comments, quotes, ticks, skip white
- # if something was grabbed, including comment, return it now
- if (skip_comments_etc())
- return;
- else if (clip == "" || error != 0)
- {
- toktype = EOF;
- return;
- }
-
- if (match(clip, /^[A-Za-z_](\w|_)*/) ||
- match(clip, /^\.\.\./)) #name - note "..." treated as name.
- {
- tok = substr(clip, 1, RLENGTH)
- clip = substr(clip, RLENGTH+1)
- toktype = NAME
- return
- }
- if (match(clip, /^([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?[fFlL]?/) ||
- match(clip, /^0[0-7]+(u|U)?(l|L)?/) ||
- match(clip, /^0(x|X)[0-9a-fA-F]+(u|U)?(l|L)?/)) #float or int
- toktype = NUMBER;
- else if (match(clip, /^(<<=|>>=|&=|\^=|\|=)/)) #bit assign
- toktype = BITASSIGNOP
- else if (match(clip, /^(\+=|-=|\*=|\/=|%=)/)) #assign, inc
- toktype = ASSIGNOP
- else if (match(clip, /^\|\|/))
- toktype = LEX_OR
- else if (match(clip, /^&&/))
- toktype = LEX_AND
- else if (match(clip, /^(<=|==|!=|>=)/)) #relational
- toktype = RELOP
- else if (match(clip, /^(<<|>>)/)) #shift
- toktype = SHIFT
- else if (match(clip, /^\+\+/))
- toktype = INCREMENT
- else if (match(clip, /^--/))
- toktype = DECREMENT
- else if (match(clip, /^->/) || match(clip, /^->\*/))
- toktype = POINTER
- else if (match(clip, /^\./) || match(clip, /^\.\*/))
- toktype = MEMBEROP
- else if (match(clip, /^./)) #everything else
- {
- #TO DO trap illegal tokens, eg "@"
- toktype = substr(clip,1,1)
- }
- else
- require(0, "Unexpected empty clip");
- tok = substr(clip, 1, RLENGTH)
- clip = substr(clip, RLENGTH+1)
- if (error != 0)
- toktype = EOF;
- }
-
- # grab comments, quotes, ticks, skip white
- function skip_comments_etc()
- {
- sub(/^[ \t\r]+/, "", clip) #remove leading blanks and tabs
- # is it a one-line comment?
- if (match(clip, /^\/\/[^\r]*\r/))
- {
- tok = substr(clip, 1, RLENGTH-1)
- clip = substr(clip, RLENGTH+1)
- sub(/^[ \t\r]+/, "", clip) #remove leading blanks and tabs
- toktype = COMMENT
- # nice touch, put a space at start of comment if missing
- if (!match(tok, /^\/\/ /))
- tok = "// " substr(tok, 3);
- return 1;
- }
- # or a multi-line comment?
- else if(match(clip, /^\/\*/))
- {
- GetComment();
- sub(/^[ \t\r]+/, "", clip) #remove leading blanks and tabs
- toktype = COMMENT
- return 1;
- }
- # or a string?
- else if(match(clip, /^"/))
- {
- GetString();
- sub(/^[ \t\r]+/, "", clip) #remove leading blanks and tabs
- toktype = STRING
- return 1;
- }
- # or a tick thingy?
- else if(match(clip, /^'/))
- {
- GetCharConstant();
- sub(/^[ \t\r]+/, "", clip) #remove leading blanks and tabs
- toktype = CHAR_CONSTANT
- return 1;
- }
- # otherwise, return 0 meaning nothing significant captured
- else
- return 0;
- }
-
- # Extract /*...*/ style comment from clip
- function GetComment( c, cp, i, len)
- {
- tok = "";
- i = 4;
- for (len = length(clip); i <= len; ++i)
- {
- c = substr(clip, i-1, 1);
- cp = substr(clip, i, 1);
- if (c == "*" && cp == "/")
- {
- tok = substr(clip, 1, i);
- clip = substr(clip, i+1)
- # Nice(?) touch, convert to inline if wanted
- if (convert_comments)
- {
- sub(/^\/\*/, "//", tok);
- sub(/\*\/$/, "", tok);
- gsub(/\r[ \t]*/, "&// ", tok);
- # put a space at start of comment if missing
- if (!match(tok, /^\/\/ /))
- tok = "// " substr(tok, 3);
- }
- return;
- }
- }
- require(0, "unterminated comment")
- }
-
- # Get standard C string
- function GetString( len, c, i, temp, esc)
- {
-
- len = length(clip);
- i = 2;
- for (esc = 0; i <= len; ++i)
- {
- c = substr(clip, i, 1);
- if (c == "\"")
- {
- if (esc == 0 || esc%2 == 0)
- {
- tok = substr(clip,1,i)
- clip = substr(clip, i+1)
- return;
- }
- else
- esc = 0;
- }
- else if (c == "\\")
- {
- if (substr(clip, i+1, 1) == "\r") #end of line, string continued
- {
- esc = 0;
- }
- else
- ++esc;
- }
- else if (c == "\r")
- {
- if (substr(clip, i-1, 1) == "\\") #string continued properly
- {
- ;
- }
- else
- require(0, "unterminated string");
- }
- else
- esc = 0;
- }
- require(0, "unterminated string");
- }
-
- # Get a thing in ticks''
- function GetCharConstant( len, c, i, esc)
- {
- len = length(clip)
- i = 2;
- for (esc = 0; i <= len; ++i)
- {
- c = substr(clip, i, 1)
- if (c == "'")
- {
- if (esc == 0 || esc%2 == 0)
- {
- tok = substr(clip,1,i)
- clip = substr(clip, i+1)
- return;
- }
- else
- esc = 0
- }
- else if (c == "\\")
- ++esc
- else if (c == "\r")
- require(0, "unterminated char constant")
- else
- esc = 0
- }
- require(0, "unterminated char constant")
- }
-
- # If assertion failed, stop work and print message to standard error
- # (Note contents of stderr are typically not flushed until you stop this program)
- function require(assertion, message)
- {
- if (assertion == 0)
- {
- error = 1;
- print message >> "stderr";
- toktype = EOF; # a bit of a hack, stop the lexer no matter what it takes
- }
- }
-
-